-- UIGameAchiv
-- Created by chengb Sep/11/2015
-- 成就界面

require "game/ui/form/achievement/UIGameAchivInfo"

UIGameAchiv = class("UIGameAchiv", function()
    return cc.Layer:create();
end);

function UIGameAchiv.create()
    return UIGameAchiv.new();
end

-- 标签页
local TAB_TYPE_LIST = {
    ACHIV_TYPE_SLIME,    -- 冈布奥
    ACHIV_TYPE_DUNGEON,  -- 迷宫
    ACHIV_TYPE_SPECIAL,  -- 特殊
};

-- 标签页标题
local TAB_NAME_MAP;

-- 构造函数
function UIGameAchiv:ctor()
    self:setName("UIGameAchiv");

    -- 标签页标题
    TAB_NAME_MAP = {
        [ACHIV_TYPE_SLIME]   = getLocStr("slime"),
        [ACHIV_TYPE_DUNGEON] = getLocStr("dungeon"),
        [ACHIV_TYPE_SPECIAL] = getLocStr("special"),
    };

    -- 初始化
    local node = cc.CSLoader:createNode("layout/achievement/GameAchiv.csb");
    self:addChild(node);
    self.node = node;

    -- 初始化
    self:init();

    -- 注册点击事件
    self:registerTouchEvent();

    -- 注册事件处理回调函数
    self:registerEventCallback();

    -- 重绘
    self:redraw();

    -- 适配
    self:resize();
end

-- 适配
function UIGameAchiv:resize()
    local node = self.node;

    -- bg居中显示并充满整个屏幕
    AlignM.fitToScreen(node, "bg");

    -- CT居中并缩放至合适大小
    AlignM.alignToCenter(node, "CT");

    -- BT置于底部并缩放至合适大小
    AlignM.alignToBottomCenter(node, "BT");
end

-- 初始化
function UIGameAchiv:init()
    -- 默认选择第一个标签页
    self.achivType = TAB_TYPE_LIST[1];

    self.tabs = {};
    for i, achivType in pairs(TAB_TYPE_LIST) do

        local tabNode  = findChildByName(self.node, "CT/tab/tab"..i);
        table.insert(self.tabs, tabNode);

        -- 为每个标签绑定成就类型
        local icon = findChildByName(tabNode, "icon");
        icon.achivType = achivType;
    end

    -- 记录下成就列表
    self.achivList = self:getAchivList();

    -- 记录滚动容器原始宽高
    -- 切换标签页时，滚动容器的内部滚动区域可能会发生变化，因此这里需要将原始宽高记录下来
    local scrollview = findChildByName(self.node, "CT/scrollview");
    scrollview.initInnerHeight = scrollview:getInnerContainerSize().height;
    scrollview.initInnerWidth  = scrollview:getInnerContainerSize().width;
    self.scrollview = scrollview;

    for i = 1, #self.tabs do
        local tab = self.tabs[i];
        tab:setPositionY(tab:getPositionY() + 100);
    end

    -- tab的动画效果
    performWithDelay(self, function() self:playTabEffect(); end, 0.2);
end

-- 页签动画效果
function UIGameAchiv:playTabEffect()
    -- 带窗口动画播放结束后，页签从上面往下掉
    for i = 1, #self.tabs do
        local tab = self.tabs[i];
        local pos = cc.p(tab:getPosition());
        local delay = cc.DelayTime:create(0.2 * (i - 1));
        local moveDown = cc.MoveTo:create(0.2, cc.p(pos.x, pos.y - 100 - 5));
        local moveBack = cc.MoveTo:create(0.2, cc.p(pos.x, pos.y - 100));
        local action = cc.Sequence:create(delay, moveDown, moveBack);
        tab:runAction(action);
    end
end

-- 重绘
function UIGameAchiv:redraw()
    -- 设置标题
    local titleLabel = findChildByName(self.node, "CT/title");
    TextStyleM.setTextStyle(titleLabel, TextStyleM.TEXT_SIZE_LARGE, TextStyleM.TEXT_COLOR_ORANGE, true, -4, nil, nil, nil, nil, true);
    titleLabel:setString(getLocStr("achievement_title"));

    -- 重绘积分信息
    self:redrawScoreInfo();

    -- 重绘成就信息列表
    self:redrawAhivList();

    -- 重绘标签页
    self:redrawTabs();
end

-- 重绘标签页
function UIGameAchiv:redrawTabs()
    for _, tabNode in pairs(self.tabs) do
        local iconImg   = findChildByName(tabNode, "icon");
        local lightImg = findChildByName(tabNode, "light");
        local titleLabel = findChildByName(tabNode, "title");
        local achivType = iconImg.achivType;

        local kerning = 0;

        if achivType == ACHIV_TYPE_SLIME then
            kerning = -3;
        end
        if not isFullWidthLang() then
            kerning = -3;
        end
        local tabStr = TAB_NAME_MAP[achivType];
        TextStyleM.setOutlineStyle(titleLabel, TextStyleM.TEXT_OUTLINE_SIZE, TextStyleM.TEXT_OUTLINE_COLOR_DARK);
        TextStyleM.setTextStyle(titleLabel, TextStyleM.TEXT_SIZE_SMALL2, TextStyleM.TEXT_COLOR_BROWN_YELLOW, true, kerning, nil, nil, nil, nil, nil, TextStyleM.getTextScale(tabStr, 6));

        local normalColor = TextStyleM.TEXT_COLOR_NORMAL;
        local blendColor  = TextStyleM.TEXT_COLOR_BLEND;

        if self.achivType == achivType then
            -- 被选中的标签高亮显示
            lightImg:setVisible(true);
            iconImg:setHighlighted(true);
            iconImg:setTouchEnabled(false);
            iconImg:setColor(normalColor);
            titleLabel:setColor(normalColor);
        else
            lightImg:setVisible(false);
            iconImg:setHighlighted(false);
            iconImg:setTouchEnabled(true);
            iconImg:setColor(blendColor);
            titleLabel:setColor(blendColor);
        end
        titleLabel:setString(tabStr);
    end
end

-- 重绘积分信息
function UIGameAchiv:redrawScoreInfo()
    local bubbleImg = findChildByName(self.node, "CT/bubble");
    local takeLabel = findChildByName(bubbleImg, "can_take");
    local scoreDescLabel = findChildByName(bubbleImg, "score_desc");
    local scoreLabel = findChildByName(bubbleImg, "score");

    -- 当前有奖励可领取
    if GameAchievementM.canTakeBonus() then
        -- 播放气泡动画
        playBubbleAnima(bubbleImg, false, 0.78);
        takeLabel:setVisible(true);
        scoreDescLabel:setVisible(false);
        scoreLabel:setVisible(false);
        TextStyleM.setTextStyle(takeLabel, TextStyleM.TEXT_SIZE_MIDDLE, TextStyleM.TEXT_COLOR_BEIGE, true, -4, nil, nil, nil, nil, true);
        takeLabel:setString(getLocStr("can_take_bonus"));
    else
        bubbleImg:stopAllActions();
        takeLabel:setVisible(false);
        scoreDescLabel:setVisible(true);
        scoreLabel:setVisible(true);

        TextStyleM.setTextStyle(scoreDescLabel, TextStyleM.TEXT_SIZE_MIDDLE, TextStyleM.TEXT_COLOR_BEIGE, true, -4, nil, nil, nil, nil, true);
        TextStyleM.setTextStyle(scoreLabel, TextStyleM.TEXT_SIZE_MIDDLE, TextStyleM.TEXT_COLOR_LIGHT_YELLOW, true, -4, nil, nil, nil, nil, true);

        -- 计算当前已累积的积分
        local curScore = GameAchievementM.calcCumulateScore();
        scoreDescLabel:setString(getLocStr("achievement_point"));
        scoreLabel:setString(curScore);
    end
end

-- 获取排序后的成就信息列表
function UIGameAchiv:getAchivList()
    local achivIdList = GameAchievementM.getIdsByType(self.achivType);
    local achivList = {};
    for _, id in pairs(achivIdList) do
        table.insert(achivList, GameAchievementM.query(id));
    end

    -- 规则：优先按照sort_priority排，sort_priority相同时再按照id排
    local function sortFunc(info1, info2)
        if info1.sort_priority == info2.sort_priority then
            return info1.id < info2.id;
        else
            return info1.sort_priority < info2.sort_priority;
        end
    end

    table.sort(achivList, sortFunc);
    return achivList;
end

-- 重绘成就信息列表
function UIGameAchiv:redrawAhivList()
    local scrollview = self.scrollview;
    scrollview:removeAllChildren();
    scrollview:jumpToTop();

    local itemNode = cc.CSLoader:createNode("layout/achievement/GameAchivItem.csb");

    -- 图标间距(横向)
    local wGap = 0;

    -- 图标间距(纵向)
    local hGap = 0;

    -- 格子宽度
    local itemWidth = 0;

    -- 格子高度
    local itemHeight = 61;

    -- 左边距
    local leftWGap = 1;

    -- 行间距
    local topGap = 0;
    local bottomHGap = 0;

    -- 单页最大可容纳列数
    local MIN_GRID_COLUMN = 1;

    -- 刷新数据
    self.achivList = self:getAchivList();

    -- 获取记录总数
    local totalNum = #self.achivList;

    -- 初始化滚动条
    ScrollTool.initScrollGridsVertical(self, scrollview, itemNode, totalNum, MIN_GRID_COLUMN, wGap, hGap, itemWidth, itemHeight, topGap, bottomHGap, leftWGap, self.registerItemTouchEvent, self.initAchiveItem);

    -- 添加滑块
    UIIndicator.attach(scrollview);
end

function UIGameAchiv:initAchiveItem(child, index)
    local config = self.achivList[index];
    local id = config.id;
    child.id = id;

    -- 显示成就图标
    local icon = config["icon"];
    local iconImg = findChildByName(child, "icon");
    iconImg:loadTexture(getAchivIconPath(icon));

    -- 冈布奥成就直接使用对应冈布奥图标
    if config["type"] == ACHIV_TYPE_SLIME then
        local pet_id = config["rule_arg"]["class_id"];
        if pet_id ~= nil then
            icon = PetM.getDefaultIcon(pet_id);
            if not PetM.getMyPet(pet_id) then
                -- 如果该冈布奥未激活，显示灰色轮廓
                iconImg:loadTexture(getHeroSilhouetteSmallIconPath(icon));
            else
                -- 已激活的，直接用冈布奥小图标
                iconImg:loadTexture(getSmallHeroIconPath(icon));
                iconImg:setScale(1.0);
            end
        end
    end

    -- 显示成就描述（名称 + 进度）
    local descLabel = findChildByName(child, "desc");
    local name = config["name"];
    local curProgress = GameAchievementM.getProgress(id);
    local progress = config["progress"];
    local ruleArg = config["rule_arg"];

    if type(ruleArg) == "table" and ruleArg["minute_to_hour"] == 1 then
        -- 分钟转换成小时
        progress = math.floor(progress/60);
        curProgress = math.floor(curProgress/60);
    end

    local desc = name;
    if progress > 1 then
        desc = string.format("%s %d/%d", name, curProgress, progress);
    end
    descLabel:setString(desc);

    -- 显示成就星级
    local rank;
    if GameAchievementM.isCompleted(id) then
        -- 已经完成了
        rank = config["rank"];
    else
        -- 未完成的成就，显示上一个成就的阶位
        rank = config["rank"] - 1;
    end
    local maxRank = GameAchievementM.getMaxRank(id);
    if maxRank > 0 then
        local rankNode = findChildByName(child, "rank_node");
        local lightStarPath = "images/ui/symbol/star_little.png";
        local darkStarPath  = "images/ui/symbol/star_little2.png";
        local starLayer = createStarLayerEx(rank, maxRank,
            lightStarPath, darkStarPath, "right", -0.6);

        if starLayer then
            rankNode:removeAllChildren();
            rankNode:addChild(starLayer);
        end
    end

    -- 该项成就是否完成
    local isCompleted = GameAchievementM.isCompleted(id);
    local takenMarkImg = findChildByName(child, "taken_mask");

    -- 如果已经完成，用蓝色字体显示，否则用默认字体
    if isCompleted then
        TextStyleM.setTextStyle(descLabel, TextStyleM.TEXT_SIZE_SMALL, TextStyleM.TEXT_COLOR_BLUE);

        -- 显示已完成的蒙版
        takenMarkImg:setVisible(true);
    else
        TextStyleM.setTextStyle(descLabel, TextStyleM.TEXT_SIZE_SMALL, TextStyleM.TEXT_COLOR_DARK_BROWN);
        takenMarkImg:setVisible(false);
    end

    return child;
end

-- 注册格子点击事件
function UIGameAchiv:registerItemTouchEvent(node)
    local touchImg = findChildByName(node, "touch_bg");
    local function onBgClick(sender, eventType)
        if eventType == ccui.TouchEventType.ended then
            self:onChildClick(node);
            AudioM.playFx("button_caption");
        end
    end
    touchImg:addTouchEventListener(onBgClick);
end

-- 成就被点击的处理
function UIGameAchiv:onChildClick(child)
    local id = child.id;

    -- 显示成就信息界面
    local uiForm = UIGameAchivInfo.create(id);
    UIMgr.getCurrentScene():removeFormByName("UIGameAchivInfo");
    UIMgr.getCurrentScene():addForm(uiForm);
end

-- 注册点击事件
function UIGameAchiv:registerTouchEvent()
    -- 注册返回按钮点击事件
    local btnBack = findChildByName(self.node, "BT/btn_back");
    local function onBackClick(sender, eventType)
        if eventType == ccui.TouchEventType.ended then
            -- 关闭当前界面
            AudioM.playFx("button_return");
            UIMgr.getCurrentScene():removeFormByName("UIGameAchiv");
        end
    end
    AddBackEventHandler(self, btnBack, onBackClick);
    TextStyleM.setTextStyle(btnBack, TextStyleM.TEXT_SIZE_MIDDLE, TextStyleM.TEXT_COLOR_BROWN_YELLOW, true);
    btnBack:setTitleText(getLocStr("btn_text_back"));

    -- 注册冒泡点击事件
    local bubbleImg = findChildByName(self.node, "CT/bubble");
    local function onBubbleClick(sender, eventType)
        if eventType == ccui.TouchEventType.ended then
            -- 显示奖励领取
            local bonusInfo = self:calcBonus();
            if type(bonusInfo.bonus) ~= "table" or #bonusInfo.bonus == 0 then
                cclog("已经领取了所有的成就奖励。");
                return;
            end

            local function callback()
                Operation.cmd_take_game_achiv_bonus();
            end

            local canTake = bonusInfo.canTake or false;
            local score = bonusInfo.score;
            local bonus = bonusInfo.bonus;
            local title = getLocStr("achievement_bonus");
            local curScore = GameAchievementM.calcCumulateScore();
            local msg = string.format(getLocStr("achievement_bonus_tip"), score, curScore, score);
            showBonusNotifyForm(title, bonus, callback, msg,
                getLocStr("take_bonus"), canTake, true);
        end
    end
    bubbleImg:addTouchEventListener(onBubbleClick);

    -- 注册各个标签页点击事件
    for _, tabNode in pairs(self.tabs) do
        local iconImg = findChildByName(tabNode, "icon");
        local function onTabClick(sender, eventType)
            if eventType == ccui.TouchEventType.ended then
                self.achivType = sender.achivType;

                -- 重绘标签页
                self:redrawTabs();

                -- 重绘成就列表
                self:redrawAhivList();
                AudioM.playFx("button_spell");
            end
        end
        iconImg:addTouchEventListener(onTabClick);
    end
end

-- 计算奖励信息
function UIGameAchiv:calcBonus()
    local bonusInfo = GameAchievementM.calcBonus();
    if type(bonusInfo.bonus) == 'table' and #bonusInfo.bonus > 0 then
        -- 当前有奖励可领取，直接返回该奖励
        bonusInfo.canTake = true;
        return bonusInfo;
    end

    -- 没有奖励可领取，返回下一个可领取的奖励
    return GameAchievementM.calcNextBonus();
end

-- 注册事件处理回调函数
function UIGameAchiv:registerEventCallback()
    -- 注册领取成就奖励的事件回调
    EventMgr.register("UIGameAchiv", event.GAME_ACHIV_BONUS, function(args)
        local bonusList = args.bonus;

        if type(bonusList) == "table" and #bonusList > 0 then
            local bonusHero = false;
            if type(bonusList[1]) == "table" and type(bonusList[1][1]) == "number" and bonusList[1][1] == 3 then
                bonusHero = true;
            elseif type(bonusList[1]) == "number" and bonusList[1] == 3 then
                bonusHero = true;
            end
            -- 奖励冈布奥则不显示
            if not bonusHero then
                -- 显示奖励领取窗口
                showBonusNotifyForm(getLocStr("achievement_bonus"), bonusList);
            end
        end

        -- 重绘气泡
        self:redrawScoreInfo();
    end);

    -- 注册获得焦点的回调
    EventMgr.register("UIGameAchiv", event.FOCUS_CHANGED, function(para)
        if para["get"] == "UIGameAchiv" then
            UIMgr:getCurrentScene().topMenu:show(TOPMENU_FRAME_MONEY, TOPMENU_FRAME_GEM);
        end
    end);

    self:registerScriptHandler(function(ev)
        if ev == "exit" then
            cclog("UIGameAchiv 界面析构清理");
            EventMgr.removeAll("UIGameAchiv");

        elseif ev == "enter" then

        end
    end);
end